package com.nanhai.buddhist.college.module.collegebase.service.studentroll;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nanhai.buddhist.college.framework.common.pojo.PageResult;
import com.nanhai.buddhist.college.framework.common.util.collection.CollectionUtils;
import com.nanhai.buddhist.college.framework.common.util.number.NumberUtils;
import com.nanhai.buddhist.college.framework.datapermission.core.annotation.DataPermission;
import com.nanhai.buddhist.college.framework.security.core.util.SecurityFrameworkUtils;
import com.nanhai.buddhist.college.module.collegebase.api.student.dto.StudentRespDTO;
import com.nanhai.buddhist.college.module.collegebase.api.student.vo.UpdatePasswordVO;
import com.nanhai.buddhist.college.module.collegebase.api.teacher.vo.ClassesStudentListPageVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.studentroll.vo.StudentRollCheckReqVo;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.studentroll.vo.StudentRollCreateReqVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.studentroll.vo.StudentRollExportReqVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.studentroll.vo.StudentRollPageReqVO;
import com.nanhai.buddhist.college.module.collegebase.controller.admin.studentroll.vo.StudentRollUpdateReqVO;
import com.nanhai.buddhist.college.module.collegebase.convert.studentroll.StudentRollConvert;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.classes.ClassesDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.classes.ClassesInfoDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.rollchecklog.RollCheckLogDO;
import com.nanhai.buddhist.college.module.collegebase.dal.dataobject.studentroll.StudentRollDO;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.classes.ClassesMapper;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.rollchecklog.RollCheckLogMapper;
import com.nanhai.buddhist.college.module.collegebase.dal.mysql.studentroll.StudentRollMapper;
import com.nanhai.buddhist.college.module.collegebase.enums.ErrorCodeConstants;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import static com.nanhai.buddhist.college.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.nanhai.buddhist.college.module.collegebase.enums.ErrorCodeConstants.IDENTITY_CARD_NUMBER_HAVE_EXISTS;
import static com.nanhai.buddhist.college.module.collegebase.enums.ErrorCodeConstants.STUDENT_NUMBER_HAVE_EXISTS;
import static com.nanhai.buddhist.college.module.collegebase.enums.ErrorCodeConstants.STUDENT_ROLL_NOT_EXISTS;

/**
 * 学员信息 Service 实现类
 *
 * @author AKai
 */
@Service
@Validated
public class StudentRollServiceImpl implements StudentRollService {

    @Resource
    private StudentRollMapper studentRollMapper;

    @Resource
    private ClassesMapper classesMapper;

    @Resource
    private RollCheckLogMapper rollCheckLogMapper;

    @Resource
    private PasswordEncoder passwordEncoder;


    @Override
    public String createStudentRoll(StudentRollCreateReqVO createReqVO) {
        // 插入
        StudentRollDO studentRoll = StudentRollConvert.INSTANCE.convert(createReqVO);
        // 设置学院、系部、专业、班级 昵称
        this.setName(studentRoll);

        // 身份证 学号唯一性校验
        checkIdAndNumber(studentRoll);

        // 获取密码
        String passWord = getPassWord(studentRoll);
        studentRoll.setPassword(passWord);
        // 返回
        studentRollMapper.insert(studentRoll);
        return studentRoll.getId();
    }

    private void checkIdAndNumber(StudentRollDO studentRoll) {
        Long idCount = studentRollMapper.selectCount(new LambdaQueryWrapper<StudentRollDO>()
                .eq(StudentRollDO::getIdentityCardNumber, studentRoll.getIdentityCardNumber()));
        if (ObjectUtil.isNotNull(idCount) && idCount > 0) {
            throw exception(IDENTITY_CARD_NUMBER_HAVE_EXISTS);
        }

        Long numberCount = studentRollMapper.selectCount(new LambdaQueryWrapper<StudentRollDO>()
                .eq(StudentRollDO::getStudentNumber, studentRoll.getStudentNumber()));
        if (ObjectUtil.isNotNull(numberCount) && numberCount > 0) {
            throw exception(STUDENT_NUMBER_HAVE_EXISTS);
        }
    }

    private void updatedCheckIdAndNumber(StudentRollDO studentRoll) {
        Long idCount = studentRollMapper.selectCount(new LambdaQueryWrapper<StudentRollDO>()
                .eq(StudentRollDO::getIdentityCardNumber, studentRoll.getIdentityCardNumber())
                .ne(StudentRollDO::getId,studentRoll.getId()));
        if (ObjectUtil.isNotNull(idCount) && idCount > 0) {
            throw exception(IDENTITY_CARD_NUMBER_HAVE_EXISTS);
        }

        Long numberCount = studentRollMapper.selectCount(new LambdaQueryWrapper<StudentRollDO>()
                .eq(StudentRollDO::getStudentNumber, studentRoll.getStudentNumber())
                .ne(StudentRollDO::getId,studentRoll.getId()));
        if (ObjectUtil.isNotNull(numberCount) && numberCount > 0) {
            throw exception(STUDENT_NUMBER_HAVE_EXISTS);
        }
    }
    @NotNull
    private String getPassWord(StudentRollDO studentRoll) {
        String passWord = "123456";
        String substring = StringUtils.substring(studentRoll.getIdentityCardNumber(), -6);
        if (StringUtils.isNotBlank(substring)) {
            passWord = substring;
        }
        String encode = passwordEncoder.encode(passWord);
        if (StringUtils.isNotBlank(encode)) {
            passWord = encode;
        }
        return passWord;
    }

    private void setName(StudentRollDO studentRoll) {
        ClassesInfoDO classesInfoDO = classesMapper.selectClassBaseInfoByClassesIdSelectOne(studentRoll.getClassesId());
        if (ObjectUtil.isNull(classesInfoDO)) {
            throw exception(ErrorCodeConstants.NOT_CLASSES_INFO_ERROR);
        }
        studentRoll.setDepartment(classesInfoDO.getDepartmentsName());
        studentRoll.setCollege(classesInfoDO.getCollegeName());
        studentRoll.setClassGrade(classesInfoDO.getClassesName());
        studentRoll.setMajor(classesInfoDO.getProfessionsName());
        studentRoll.setSerialNumber(NumberUtils.getCodeByServ("XY"));
    }

    @Override
    public void updateStudentRoll(StudentRollUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateStudentRollExists(updateReqVO.getId());


        // 更新
        StudentRollDO updateObj = StudentRollConvert.INSTANCE.convert(updateReqVO);
        // 身份证 学号唯一性校验
        updatedCheckIdAndNumber(updateObj);

        // 设置学院、系部、专业、班级 昵称
        this.setName(updateObj);
        studentRollMapper.updateById(updateObj);
    }

    @Override
    public void deleteStudentRoll(String id) {
        // 校验存在
        this.validateStudentRollExists(id);
        // 删除
        studentRollMapper.deleteById(id);
    }

    private void validateStudentRollExists(String id) {
        if (studentRollMapper.selectById(id) == null) {
            throw exception(STUDENT_ROLL_NOT_EXISTS);
        }
    }

    @DataPermission(enable = false)
    @Override
    public StudentRollDO getStudentRoll(String id) {
        return studentRollMapper.selectById(id);
    }

    @Override
    public List<StudentRollDO> getStudentRollList(Collection<String> ids) {
        return CollectionUtils.isEmpty(ids) ? Collections.emptyList() : studentRollMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<StudentRollDO> getStudentRollPage(StudentRollPageReqVO pageReqVO) {
        return studentRollMapper.selectPage(pageReqVO);
    }

    @Override
    public List<StudentRollDO> getStudentRollList(StudentRollExportReqVO exportReqVO) {
        return studentRollMapper.selectList(exportReqVO);
    }

    @Override
    @Transactional
    public void checkStudentRoll(StudentRollCheckReqVo req) {
        StudentRollDO studentRollDO = studentRollMapper.selectById(req.getId());

        RollCheckLogDO rollCheckLogDO = new RollCheckLogDO();
        rollCheckLogDO.setCheckTime(new Date());
        rollCheckLogDO.setNewStatus(req.getCheckStatus());
        rollCheckLogDO.setOldStatus(studentRollDO.getCheckStatus());
        rollCheckLogDO.setStudentId(req.getId());
        rollCheckLogMapper.insert(rollCheckLogDO);

        String userId = SecurityFrameworkUtils.getLoginUserId();
        studentRollDO.setCheckUser(userId);

        studentRollDO.setCheckTime(new Date());
        // studentRollDO.setCheckUser();
        studentRollDO.setCheckStatus(req.getCheckStatus());
        studentRollDO.setCheckRemark(req.getCheckRemark());
        studentRollMapper.updateById(studentRollDO);
    }

    @Override
    public List<StudentRollDO> getStudentRollListByStr(String findStr) {
        return studentRollMapper.selectList(new LambdaQueryWrapper<StudentRollDO>()
                .like(StudentRollDO::getStudentName, findStr)
                .or().like(StudentRollDO::getLegalName, findStr)
                .or().like(StudentRollDO::getStudentNumber, findStr)
                .or().like(StudentRollDO::getSerialNumber, findStr));
    }

    @Override
    public PageResult<StudentRollDO> getStudentRespDTOByClassesId(ClassesStudentListPageVO req) {
        Page<StudentRollDO> page = new Page<>(req.getPageNo(), req.getPageSize());
        Page<StudentRollDO> selectPage = studentRollMapper.selectPage(page, new LambdaQueryWrapper<StudentRollDO>().eq(StudentRollDO::getClassesId, req.getId()));
        PageResult<StudentRollDO> res = new PageResult<>();
        res.setList(selectPage.getRecords());
        res.setTotal(selectPage.getTotal());
        return res;
    }

    @Override
    public StudentRollDO getStudentByUserName(String studentUsername) {
        StudentRollDO studentRollDO = studentRollMapper.selectOne(new LambdaQueryWrapper<StudentRollDO>().eq(StudentRollDO::getStudentNumber, studentUsername));
        return studentRollDO;
    }

    @Override
    public void updatedStudentPassword(UpdatePasswordVO req) {
        StudentRollDO studentRollDO = studentRollMapper.selectById(req.getId());
        if (ObjectUtil.isEmpty(studentRollDO)) {
            throw exception(ErrorCodeConstants.SELECT_NULL_ERROR);
        }
        String encode = passwordEncoder.encode(req.getPassWord());
        studentRollDO.setPassword(encode);
        studentRollMapper.updateById(studentRollDO);
    }

    @Override
    public List<StudentRollDO> getStudentListByClassesId(String classesId) {
        if (StringUtils.isBlank(classesId)) {
            return new ArrayList<>();
        }
        return studentRollMapper.selectList(new LambdaQueryWrapper<StudentRollDO>().eq(StudentRollDO::getClassesId,classesId));
    }

}
